package com.net.io.netty.emebededchannel;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.TooLongFrameException;

import java.util.List;

/**
 * 扩展 ByteToMessageDecoder以将入站字节解码为消息
 *
 * @author zhangtengfei
 * @date 2022/2/17 15:09
 */
public class FrameChunkDecoder extends ByteToMessageDecoder {

    /**
     * 三、异常处理测试
     * <p>
     * 应用程序通常需要执行比转换数据更加复杂的任务。例如，你可能需要处理格式不正确的输入或者过量的数据。
     */
    private final int maxFrameSize;

    /**
     * 如果所读取的字节数超出了某个特定的限制，我们将会抛出一个 TooLongFrameException
     * 这是一种经常用来防范资源被耗尽的方法。
     * <p>
     * 设定最大的帧大小已经被设置为 3 字节。如果一个帧的大小超出了该限制，那么程序将会丢弃它的字节，并抛出一个TooLongFrameException。
     * 位于 ChannelPipeline 中的其他 ChannelHandler 可以选择在exceptionCaught()方法中处理该异常或者忽略它。
     *
     * @param maxFrameSize
     */
    public FrameChunkDecoder(int maxFrameSize) {
        this.maxFrameSize = maxFrameSize;
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        int readableBytes = in.readableBytes();
        if (readableBytes > maxFrameSize) {
            // 如果该帧超出允许的大小，则丢弃它并抛出一个 TooLongFrameException
            in.clear();
            throw new TooLongFrameException();
        }
        // 否则，从 ByteBuf 中读取一个新的帧
        ByteBuf buf = in.readBytes(readableBytes);
        // 将该帧添加到解码 读取一个新的帧消息的 List 中
        out.add(buf);
    }
}

